﻿using System;
using System.Collections.Generic;
using AvantGameMachine.Graphics;
using AvantGameMachine.Input;
using AvantGameMachine.Events;
using AvantGameMachine.Graphics.InternalObjects;
using AvantGameMachine.FileSystem;
using AvantGameMachine.DataManagement;
using AvantGameMachine.Timers;
using AvantGameMachine.States;
using AvantGameMachine.States.InternalObjects;
using AvantGameMachine.Clients;

namespace AvantGameMachine
{
    class AGMPlatform
    {
        private static AGMPlatform myInstance = null;
        private static OpenGLDevice device = null;
        private static EngineTopScene topScene = null;
        private static InputManager iManager = null;
        private static EventManager eManager = null;
        private static FileSystemManager fSystem = null;
        private static SystemDataContainer sdc = null;
        private static ConfigurationManager cManager = null;
        private static Log logi = null;
        private static TimerManager timerManager = null;
        private static TextRenderingManager trManager = null;
        private static DebugVars dVars = null;
        private static StateManager stManager = null;
        private static DebugCamera dCamera = null;
        private static ClientManager clManager = null;

        private AGMPlatform()
        {
            logi = new Log();
            timerManager = new TimerManager();
            sdc = new SystemDataContainer();
            fSystem = new FileSystemManager();
            cManager = new ConfigurationManager();
            eManager = new EventManager();
            topScene = new EngineTopScene();
            iManager = new InputManager();
            trManager = new TextRenderingManager();
            stManager = new StateManager();
            clManager = new ClientManager();
            device = new OpenGLDevice();
        }

        internal static AGMPlatform Create()
        {
            if (myInstance == null)
                myInstance = new AGMPlatform();

            return myInstance;
        }

        internal void Start()
        {
            cManager.Init();
            device.Init();
            fSystem.Init();
            trManager.Init();
            clManager.Init();
            topScene.Init(new Box(0,0,device.ScreenW,device.ScreenH));

            dCamera = topScene.CreateNewCamera<DebugCamera>("dCamera");

            // Debug vars
            dVars = dCamera.CreateNew2DObject<DebugVars>("DebugVars");
            dVars.Init(trManager.GetNewFont(new Address("console.ttf"), 12));
            dVars.PositionZ = -0.5f;

            stManager.RegisterStateProvider(new SystemStatesProvider(), "SystemStart");
            
            /*
            PlaneTexture ro = dCamera.CreateNew2DObject<PlaneTexture>("sd");
            ro.SetTexture(new Address("backm.png"));
            //            ro.Position = new PosVector(ro.Position.X, ro.Position.Y, 0.5f); // - is front

            Font ft = trManager.GetNewFont(new Address("segoepr.ttf"),64);
            TextRenderObject to = dCamera.CreateNew2DObject<TextRenderObject>("text");
            to.TextFont = ft;
            to.Text = "abcdefghij";
            to.PositionZ = -0.5f; // - is front
            to.PositionY = 100;
            */
            /*
            Face p = Face.CreateQuad(1.0f);
            RenderObject ro = dCamera.CreateNew<RenderObject>("sd");

            ro.Transpolate(p, new PosVector(0, 0, -1.0f), 1);
            Texture t = AGMPlatform.TManager.CreateTexture("backm.png");
            ro.GetFace(0).TMapping = new TextureMapping(t);

            Line l = dCamera.CreateNew<Line>("line1");
            l.StartPoint = new PosVector(0f, 0f, 0f);
            l.EndPoint = new PosVector(10f, 0f, 0f);
            l = dCamera.CreateNew<Line>("line2");
            l.StartPoint = new PosVector(0f, 0f, 0f);
            l.EndPoint = new PosVector(0f, 10f, 0f);
            l = dCamera.CreateNew<Line>("line3");
            l.StartPoint = new PosVector(0f, 0f, 0f);
            l.EndPoint = new PosVector(0f, 0f, 10f);
            l = dCamera.CreateNew<Line>("line4");
            l.StartPoint = new PosVector(0f, 0f, 0f);
            l.EndPoint = new PosVector(-10f, 0f, 0f);
            l = dCamera.CreateNew<Line>("line5");
            l.StartPoint = new PosVector(0f, 0f, 0f);
            l.EndPoint = new PosVector(0f, -10f, 0f);
            l = dCamera.CreateNew<Line>("line6");
            l.StartPoint = new PosVector(0f, 0f, 0f);
            l.EndPoint = new PosVector(0f, 0f, -10f);*/
        }

        internal void MainLoop()
        {
            device.mainloop();
        }

        internal static AGMPlatform Instance
        {
            get { return myInstance; }
        }

        internal static OpenGLDevice Device
        {
            get { return device; }
        }

        internal static EngineTopScene TopScene
        {
            get { return topScene; }
        }

        internal static InputManager IManager
        {
            get { return iManager; }
        }

        internal static EventManager EManager
        {
            get { return eManager; }
        }

        internal static FileSystemManager FSManager
        {
            get { return fSystem; }
        }

        internal static SystemDataContainer SData
        {
            get { return sdc; }
        }

        internal static ConfigurationManager CManager
        {
            get { return cManager; }
        }

        internal static Log log
        {
            get { return logi; }
        }

        internal static TimerManager TiManager
        {
            get { return timerManager; }
        }

        internal static TextRenderingManager TRManager
        {
            get { return trManager; }
        }

        internal static DebugVars DVars
        {
            get { return dVars; }
        }

        internal static StateManager StManager
        {
            get { return stManager; }
        }

        internal static Camera SystemCamera
        {
            get { return dCamera; }
        }

        internal static ClientManager ClManager
        {
            get { return clManager; }
        }
    }
}
